﻿using System.Reactive.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ReactiveUI;
using System.Reactive;
using DynamicData;
using System.ComponentModel;
using System.Diagnostics;
using System.Reactive.Concurrency;

namespace SerialPortDemo_08.ViewModel
{
    public class MainViewModel : ReactiveObject
    {
        // 第一个地址
        private string _firestAddress;
        public string FirestAddress { get => _firestAddress; set => this.RaiseAndSetIfChanged(ref _firestAddress, value); }

        // 第二个地址
        private string _secondAddress;
        public string SecondAddress { get => _secondAddress; set => this.RaiseAndSetIfChanged(ref _secondAddress, value); }

        // 第三个地址
        private string _thirdAddress;
        public string ThirdAddress { get => _thirdAddress; set => this.RaiseAndSetIfChanged(ref _thirdAddress, value); }

        // 已选择的串口号
        private string _selectedPortName;
        public string SelectedPortName { get => _selectedPortName; set => this.RaiseAndSetIfChanged(ref _selectedPortName, value); }

        // 已选择的波特率
        private int _selectedBaudRate;
        public int SelectedBaudRate { get => _selectedBaudRate; set => this.RaiseAndSetIfChanged(ref _selectedBaudRate, value); }

        // 串口打开标志
        private bool _open = false;
        public bool Open { get => _open; set => this.RaiseAndSetIfChanged(ref _open, value); }

        // 接受信息框
        private string _message;
        public string Message { get => _message; set => this.RaiseAndSetIfChanged(ref _message, value); }

        // 信息接受委托
        private Action<byte[]> Received;

        // 串口号集合
        public BindingList<string> PortNameList = new BindingList<string>();
        // 波特率计划
        public BindingList<int> BaudRateList = new BindingList<int>();

        // 打开串口命令
        public ReactiveCommand<Unit,Unit> OpenSerialCommand { get;  set; }

        // 第一个读取 命令
        public ReactiveCommand<Unit,Unit> ReadCommand { get;  set; }

        // 第二个读取 命令
        public ReactiveCommand<Unit, Unit> Read1Command { get; set; }

        public ReactiveCommand<Unit, Unit> WriteCommand { get; set; }

        private MySerialPort _serialPort = new MySerialPort();

        public MainViewModel()
        {
            PortNameList.AddRange(_serialPort.GetPortNameList());
            if (PortNameList.Count > 0) SelectedPortName = PortNameList.First();

            BaudRateList.AddRange(_serialPort.GetBaudRateList());
            if(BaudRateList.Count > 0) SelectedBaudRate = BaudRateList.First();

            OpenSerialCommand = ReactiveCommand.Create(OpenSerial);
            ReadCommand = ReactiveCommand.Create(Read);
            Read1Command = ReactiveCommand.Create(Read1);
            WriteCommand = ReactiveCommand.Create(Write);

            _serialPort.ShowLogEvent += (message) => RxApp.MainThreadScheduler.Schedule(() => Message += (message + "\r\n"));
            _serialPort.ReceivedEvent += ReceivedHandel;
        }

        /// <summary>
        /// 打开串口
        /// </summary>
        private void OpenSerial()
        {
            if(!Open)
            {
                try
                {
                    _serialPort.OpenBy(SelectedPortName, SelectedBaudRate);
                    Open = true;
                }
                catch
                {
                    Open = false;
                    MessageBox.Show("打开失败！");
                }

                return;
            }

            try
            {
                _serialPort.Close();
            } catch
            {

            }finally
            {
                Open = false;
            }
        }

        /// <summary>
        /// 第一个读取按钮
        /// </summary>
        private void Read()
        {
            try
            {
                ByteBuffer byteBuffer = new ByteBuffer(new byte[] { 0x01, 0x03, 0x00, 0x00, 0x00, 0x64, 0x44, 0x21 });

                _serialPort.Write(byteBuffer.toByteArray());

                Received = ReadResponse;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 第二个读取按钮
        /// </summary>
        private void Read1()
        {
            try
            {
                byte[] request = CRC.crc16(new byte[] { 0x01, 0x03, 0x00, 0x01, 0x00, 0x03 }); ;

                _serialPort.Write(request);

                Received = Read1Response;
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 写入按钮
        /// </summary>
        private void Write()
        {
            try
            {
                ByteBuffer requestBuffer = new ByteBuffer();
                //byte[] request = new byte[] { 0x01, 0x10, 0x00, 0x01, 0x00, 0x03, 0x06 };
                // 响应的数据
                // 0x01, 0x10, 0x00, 0x01, 0x00, 0x03, 0x06
                // 0x01 -- 从机地址；  0x10 -- 功能码；
                // 0x00 0x01 -- 起始地址
                // 0x00 0x03 -- 寄存器个数
                // 0x06 -- 字节计数
                requestBuffer.pushByteArray(new byte[] { 0x01, 0x10, 0x00, 0x01, 0x00, 0x03, 0x06 });
                requestBuffer.pushShort(short.Parse(FirestAddress));
                requestBuffer.pushShort(short.Parse(SecondAddress));
                requestBuffer.pushShort(short.Parse(ThirdAddress));

                _serialPort.Write(CRC.crc16(requestBuffer.toByteArray()));

                Received = WriteRespnose;

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void ReceivedHandel(byte[] bytes)
        {
            Received?.Invoke(bytes);
        }

        private void ReadResponse(byte[] bytes)
        {
            RxApp.MainThreadScheduler.Schedule(() => MessageBox.Show("串口有数据传来"));
        }


        private void Read1Response(byte[] buffer)
        {
            RxApp.MainThreadScheduler.Schedule(() =>
            {
                ByteBuffer byteBuffer = new ByteBuffer(buffer);

                // 响应的数据
                // 01 03 06 00 00 00 02 00 00 80 B5
                // 0x01 -- 从机地址；  0x03 -- 功能码； 0x06 -- 数据长度
                // 0x00 0x00 -- 第一个寄存器的值
                // 0x00 0x02 -- 第二个寄存器的值
                // 0x00 0x00 -- 第三个寄存器的值
                // 0x80 0xB5 -- 校验位

                byteBuffer.popByte(); // 0x01 -- 从机地址；
                byteBuffer.popByte(); // 0x03 -- 功能码；
                byteBuffer.popByte(); // 0x06 -- 数据长度

                FirestAddress = byteBuffer.popShort().ToString(); // 0x00 0x00 -- 第一个寄存器的值
                SecondAddress = byteBuffer.popShort().ToString(); // 0x00 0x02 -- 第二个寄存器的值
                ThirdAddress = byteBuffer.popShort().ToString(); // 0x00 0x00 -- 第三个寄存器的值

                MessageBox.Show("解析完成");
            });

        }

        private void WriteRespnose(byte[] buffer)
        {
            MessageBox.Show("写入成功");
        }
    }
}
